
/*
*		c9l has the following methods:
*
*		c9l.save(collection, object, [callback])
*			- *does not work cross-domain*
*			- object is stored on the server as a new document in the collection
*			- callback is called with a copy of the object with extra metadata,
*				including an _id tag
*			- if an object is saved with a specified _id, the object replaces
*				the existing object
*
*		handle = c9l.find(collection, object, callback)
*			- uses MangoDB search semantics to find matching objects in collection
*			- callback is called *once for each matching result* (may be many itmes)
*
*		handle = c9l.subscribe(collection, callback, [since])
*			- callback is called *once for each document in the collection* since the 
*				specified timestamp (continually, until handle.stop() is called)
*			- specify [since] in order to start from a known timestamp
*			- returns handle object with:
*				- handle.stop(): no longer recieve updates
*				- handle.resume(): call after stop() to re-start subscription
*				- handle.since: last seen timestamp
*/

c9l = function () {

var server = "http://root.cloud9lib.net";

var global = (function(){return this;}).call();
 
var POST = function (uri, body, callback) {

	var req = new XMLHttpRequest();
	req.open("POST", uri, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (callback) callback(req.responseText);
		}
	};
	
	req.send(body);
}

var PUT = function (uri, body) {

	var req = new XMLHttpRequest();
	req.open("PUT", uri, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) 
			if  (req.status != 200 && req.state != 201) {
			}
	};

	req.send(body);
}


var save = function (collection, obj, callback) {

	POST ("/db?c="+collection, JSON.stringify(obj), callback);
}

var GET = function (uri, callback) {

	var req = new XMLHttpRequest();
	req.open("GET", uri, true);

	req.onreadystatechange = function () {
		if (req.readyState == 4) {
			if (req.status == 200) 
				callback(req.responseText);
			else {
			}
		}
	};

	req.send();
}

var GETX = function (uri) {

	var e = document.createElement("script");
	e.src = uri;
	e.type = "text/javascript";
	document.getElementsByTagName("head")[0].appendChild(e); 
}


var find = function (collection, query, callback)	{
	GET("/db?c=" + collection + "&q=" + escape(JSON.stringify(query)), function (json) {var arr = JSON.parse(json); for (var i = 0; i < arr.length; i++) { callback(arr[i]);}} );


//TODO
	var h = handle();

	return h;
}

var callbackCounter = 0;

var registercallback = function (callback) {

	var name = "c9lCallback" + callbackCounter;
	global[name] = callback;

	callbackCounter++;

	return name;
}

var findx = function (collection, query, callback) {

	var cb = registercallback(callback);

	GETX("/db?c=" + collection + "&cb=" + cb + "&q=" + escape(JSON.stringify(query)));

//TODO 
	var h = handle();

	return h;
}

var handle = function () {

	var h = new Object();
	h.done = false;

	h.stop = function () {
		h.done = true;
	};

	return h
}

var subscribe = function (feed, callback, since) {

	if (since == null) since = 0;

	var done = false;

	var feedcallback = function (json) {

		var obj = JSON.parse(json);

		since = obj.Version;
		h.since = since;

		for (var i = 0; i < obj.Entries.length; i++) {
			GET(obj.Entries[i], function(json) {callback(JSON.parse(json));} );
		}
		
		if (done != true) {
			h.resume();
		}
	};

	var h = new Object();
	h.since = since;
	h.stop = function() {
		done = true;
	}
	h.resume = function() {
		done = false;
		GET ("/feed?id=" + feed + "&block=true&since=" + since, feedcallback);
	}

	h.resume();

	return h;
}

var subscribex = function (feed, callback, since) {

	if (since == null) since = 0;

	var cb = registercallback(callback);

	var done = false;

	var feedcallback = function (obj) {

		if (!obj || !obj.Version) {
			return;
		}	

		since = obj.Version;
		h.since = since;

		for (var i = 0; i < obj.Entries.length; i++) {
			GETX(server + obj.Entries[i] + "&cb=" + cb);
		}
		
		if (done != true) {
			h.resume();
		}
	};

	var fcb = registercallback(feedcallback);

	var h = new Object();
	h.since = since;
	h.stop = function() {
		done = true;
	}
	h.resume = function() {
		done = false;
		GETX (server + "/feed?id=" + feed + "&cb=" + fcb + "&block=true&since=" + since);
	}

	h.resume();

	return h;
}
var keywords = function() {

	var skip = ["a", "the", "it", "an", "s", "d"];

	var tags = new Object();

	for (var i = 0; i < arguments.length; i++) {
		var words = arguments[i].match(/\w+/gi);
		if (words) for (var j = 0; j < words.length; j++) {
			for (var k = 0; k < skip.length; k++) 
				if (words[j] == skip[k]) break; 
			tags[words[j]] = true;
		}
	}

	return Object.keys(tags);
}

var o = Object();

o.save = save;
o.find = findx;
o.findx = findx;
o.subscribe = subscribex;
o.subscribex = subscribex;
o.keywords = keywords;

return o;
} ();
